//type list
//$Id: typelist.h 395 2010-03-26 14:01:03Z Oleg.Bulychov $
#pragma once

#include "type_util.h"

/*
 This code is taken from the "Loki" library and slightly modified.

 The Loki Library
 Copyright (c) 2001 by Andrei Alexandrescu
 This code accompanies the book:
 Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design 
     Patterns Applied". Copyright (c) 2001. Addison-Wesley.
 Permission to use, copy, modify, distribute and sell this software for any 
     purpose is hereby granted without fee, provided that the above copyright
     notice appear in all copies and that both that copyright notice and this
     permission notice appear in supporting documentation.
 The author or Addison-Welsey Longman make no representations about the 
     suitability of this software for any purpose. It is provided "as is" 
     without express or implied warranty.
*/

namespace meta
{

//__________________________________________________________________________________
    class nulltype {};
//__________________________________________________________________________________
    template <class T, class U>
    struct typelist
    {
        typedef T Head;
        typedef U Tail;
    };
//__________________________________________________________________________________
    template
    <
        typename T1  = nulltype, typename T2  = nulltype, typename T3  = nulltype,
        typename T4  = nulltype, typename T5  = nulltype, typename T6  = nulltype,
        typename T7  = nulltype, typename T8  = nulltype, typename T9  = nulltype,
        typename T10 = nulltype, typename T11 = nulltype, typename T12 = nulltype,
        typename T13 = nulltype, typename T14 = nulltype, typename T15 = nulltype,
        typename T16 = nulltype, typename T17 = nulltype, typename T18 = nulltype
    > 
    struct make_typelist
    {
    private:
        typedef typename make_typelist
        <
            T2 , T3 , T4 , 
            T5 , T6 , T7 , 
            T8 , T9 , T10, 
            T11, T12, T13,
            T14, T15, T16, 
            T17, T18
        >
        ::Result TailResult;

    public:
        typedef typelist<T1, TailResult> Result;
    };

    template<>
    struct make_typelist<>
    {
        typedef nulltype Result;
    };
//__________________________________________________________________________________
    template <class TList, class T> struct type_append;

    template <> struct type_append<nulltype, nulltype>
    {
        typedef nulltype Result;
    };

    template <class T> struct type_append<nulltype, T>
    {
        typedef typelist<T,nulltype> Result;
    };

    template <class Head, class Tail>
    struct type_append<nulltype, typelist<Head, Tail> >
    {
        typedef typelist<Head, Tail> Result;
    };

    template <class Head, class Tail, class T>
    struct type_append<typelist<Head, Tail>, T>
    {
        typedef typelist<Head, 
                typename type_append<Tail, T>::Result>
            Result;
    };
//__________________________________________________________________________________
//__________________________________________________________________________________
//__________________________________________________________________________________
}//meta


//EOF!
